<?php
/**
 * Created by PhpStorm.
 * User: lhl
 * Date: 2019/6/4
 * Time: 15:38
 * Features: 算法相关封装
 */

namespace app\common\service;


class Algorithm
{
    /**
     * 百分比概率抽奖算法
     * @param array $dataArr 奖品数组
     * [
     *      [ 奖品标识(比如ID) => 该奖品的中奖基数 ] ,
     *      ...
     * ]
     * @return string 所中奖品标识
     */
    public static function lottery($dataArr){
        $result = '';
        //概率数组的总概率精度
        $proSum = array_sum($dataArr);
        //概率数组循环
        foreach ($dataArr as $key => $proCur) {
            $randNum = mt_rand(1, $proSum);
            if ($randNum <= $proCur) {
                $result = $key;
                break;
            } else {
                $proSum -= $proCur;
            }
        }
        unset($dataArr);
        return $result;
    }

    /**
     * 将二维数组根据pid整理成树形结构
     * @param array $data 二维数组
     * [
     *      'pid' => 父节点id,
     *      'id'  => 节点id
     * ]
     * @param int $pid 目标父节点id
     * @param $type 1：子节点以$childKey为键名作为父节点的子数组 2：排序好的一维数组
     *
     * @param bool $isUnsetEmptyChild 是否删除空的$childKey的key
     * return mixed
     */
    public static function tree($data,$pid = 0,$type = 1,$childKey = 'son',$isUnsetEmptyChild = false){
        $tree = [];
        $list = [];
        foreach($data as $k => $v)
        {
            if($v['pid'] == $pid)
            {   //找到了子节点
                if($type == 1){
                    $v[$childKey] = self::tree($data, $v['id'],1,$childKey,$isUnsetEmptyChild);
                    if(!$v[$childKey] && $isUnsetEmptyChild){
                        unset($v[$childKey]);
                    }

                    $tree[] = $v;
                }
                if($type == 2){
                    $list[] = $v;
                    $list = array_merge($list,self::tree($data,$v['id'],2,$childKey,$isUnsetEmptyChild));
                }
            }
        }
        //去重
        if($list && $type == 2){
            $list = ArrayHelper::arrayUnique($list,'id');
        }

        return $type == 1 ? $tree : $list;
    }

    /**
     * 递归删除数组中的指定key
     * @param array     $data           树形结构数据
     * @param array     $exceptFields   需要排除的字段名称
     * @param string    $childKey       子节点字段名称
    */
    public static function delTreeKey($data,array $exceptFields,$childKey = 'children'){
        foreach ($data as $key => $item){
           //删除本级别的
           foreach ($exceptFields as $k => $v){
               if(isset($item[$v])){
                   unset($data[$key][$v]);
               }
           }
           if(isset($item[$childKey]) && $item[$childKey]){
               $data[$key][$childKey] = self::delTreeKey($item[$childKey],$exceptFields,$childKey);
           }
        }

        return $data;
    }

    /**
     * 实现二维数组的笛卡尔积组合
     * @param array $arr 要进行笛卡尔积的二维数组
     * @param array $str 最终实现的笛卡尔积组合,无需传此参数
     * @return array
     */
    public static function cartesian($arr,$str = []){
        //获取并去除第一个元素
        $first = array_shift($arr);
        //判断是否是第一次进行拼接
        if($str) {
            foreach ($str as $k => $val) {
                foreach ($first as $key => $value) {
                    //最终实现的格式 1,3,76
                    //可根据具体需求进行变更
                    $str2[] = $val.','.$value;
                }
            }
        }else{
            $str2 = array_values($first);
        }

        //递归进行拼接
        if($arr){
            $str2 = self::cartesian($arr,$str2);
        }
        //返回最终笛卡尔积
        return $str2;
    }

}